/* ----------
 * backend_progress.c
 *
 *	Command progress reporting infrastructure.
 *
 *	Copyright (c) 2001-2022, PostgreSQL Global Development Group
 *
 *	src/backend/utils/activity/backend_progress.c
 * ----------
 */
#include "postgres.h"

#include "port/atomics.h"		/* for memory barriers */
#include "utils/backend_progress.h"
#include "utils/backend_status.h"


/*-----------
 * pgstat_progress_start_command() -
 *
 * 设置自己的后端条目中的 st_progress_command（和 st_progress_command_target）。 
 * 同时，将 st_progress_param 数组进行零初始化。
 *-----------
 */
void pgstat_progress_start_command(ProgressCommandType fc_cmdtype, Oid fc_relid)
{
	volatile PgBackendStatus *fc_beentry = MyBEEntry;

	if (!fc_beentry || !pgstat_track_activities)
		return;

	PGSTAT_BEGIN_WRITE_ACTIVITY(fc_beentry);
	fc_beentry->st_progress_command = fc_cmdtype;
	fc_beentry->st_progress_command_target = fc_relid;
	MemSet(&fc_beentry->st_progress_param, 0, sizeof(fc_beentry->st_progress_param));
	PGSTAT_END_WRITE_ACTIVITY(fc_beentry);
}

/*-----------
 * pgstat_progress_update_param() -
 *
 * 更新自己后端条目中 st_progress_param[]的第 index 个成员。
 *-----------
 */
void pgstat_progress_update_param(int fc_index, int64 fc_val)
{
	volatile PgBackendStatus *fc_beentry = MyBEEntry;

	Assert(fc_index >= 0 && fc_index < PGSTAT_NUM_PROGRESS_PARAM);

	if (!fc_beentry || !pgstat_track_activities)
		return;

	PGSTAT_BEGIN_WRITE_ACTIVITY(fc_beentry);
	fc_beentry->st_progress_param[fc_index] = fc_val;
	PGSTAT_END_WRITE_ACTIVITY(fc_beentry);
}

/*-----------
 * pgstat_progress_update_multi_param() -
 *
 * 更新自己后端条目中 st_progress_param[]的多个成员。 
 * 这是原子操作；读取者不会看到中间状态。
 *-----------
 */
void pgstat_progress_update_multi_param(int fc_nparam, const int *fc_index,
								   const int64 *fc_val)
{
	volatile PgBackendStatus *fc_beentry = MyBEEntry;
	int			fc_i;

	if (!fc_beentry || !pgstat_track_activities || fc_nparam == 0)
		return;

	PGSTAT_BEGIN_WRITE_ACTIVITY(fc_beentry);

	for (fc_i = 0; fc_i < fc_nparam; ++fc_i)
	{
		Assert(fc_index[fc_i] >= 0 && fc_index[fc_i] < PGSTAT_NUM_PROGRESS_PARAM);

		fc_beentry->st_progress_param[fc_index[fc_i]] = fc_val[fc_i];
	}

	PGSTAT_END_WRITE_ACTIVITY(fc_beentry);
}

/*-----------
 * pgstat_progress_end_command() -
 *
 * 重置自己后端条目中的 st_progress_command（和 st_progress_command_target）。 
 * 这表示命令的结束。
 *-----------
 */
void pgstat_progress_end_command(void)
{
	volatile PgBackendStatus *fc_beentry = MyBEEntry;

	if (!fc_beentry || !pgstat_track_activities)
		return;

	if (fc_beentry->st_progress_command == PROGRESS_COMMAND_INVALID)
		return;

	PGSTAT_BEGIN_WRITE_ACTIVITY(fc_beentry);
	fc_beentry->st_progress_command = PROGRESS_COMMAND_INVALID;
	fc_beentry->st_progress_command_target = InvalidOid;
	PGSTAT_END_WRITE_ACTIVITY(fc_beentry);
}
